home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGSCAL
/
XGRAPH.LZH
/
XGRAPH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-03-12
|
15KB
|
409 lines
{ Turbo Pascal XGRAPH suppport definitions, procedures and functions }
Const
{ Video INT 10H constants }
{ ----------------------- }
VideoInt = $10;
{ Video functions provided by VideoInt }
{ ------------------------------------ }
VidSetMode = $00; VidSetCursorType = $01;
VidSetCursorPosition = $02; VidReadCursorPosition = $03;
VidReadLightPenPosition = $04; VidSelectActiveDisplayPage = $05;
VidScrollActivePageUp = $06; VidScrollActivePageDown = $07;
VidReadAtributeCharacterAtCursor= $08; VidWriteAtributeCharacterAtCursor= $09;
VidWriteCharacterOnlyAtCursor = $0A; VidSetColorPalette = $0B;
VidWriteDot = $0C; VidReadDot = $0D;
VidWriteTeletype = $0E; VidCurrentVideoState = $0F;
VidSetPaletteRegisters = $10; VidCharacterGeneratorRoutine = $11;
VidAlternateSelect = $12; VidWriteString = $13;
VidExtendedFunctions = $6F;
{ Xgraph functions }
VidId = $A3; VidInit = $A4;
VidClear = $A5; VidRectFill = $A6;
VidLine = $A7; VidPolyFill = $A8;
VidBlit = $A9;
{ Blit and Texturing Opcodes }
Blit0 = 0; BlitSandD = 1; BlitSandND = 2; BlitS = 3;
BlitNSandD = 4; BlitD = 5; BlitSxorD = 6; BlitSorD = 7;
BlitNSandND = 8; BlitNSxorD = 9; BlitND = 10; BlitSorND = 11;
BlitNS = 12; BlitNSorD = 13; BlitNSorND = 14; Blit1 = 15;
Text0 = 0; Text1 = 1; TextS = 2; TextP = 3;
TextSorP = 4; TextSandP = 5; TextSxorP = 6; TextNP = 7;
TextSorNP = 8; TextSandNP = 9; TextSxorNP = 10;
{ Video Modes Possible }
{ -------------------- }
Video40x25BW = $00; Video40x25Color = $01;
Video80x25BW = $02; Video80x25Color = $03;
Video320x200BW = $04; Video320x200Color = $05;
Video640x200 = $06; VideoMonochrome = $07;
VideoEGA320x200 = $0D; VideoEGA640x200 = $0E;
VideoEGA640x350Mono = $0F; VideoEGA640x350Color = $10;
VideoHerculesGraphics = $11;
VideoMulti80x27 = $12; VideoMulti40x27 = $13;
VideoMulti640x400 = $14; VideoMulti320x400 = $15;
type
AdapterType = (CGA, Mono, EGAEnh, EGACga, EGAMono, MultiModeHires, MultiModeCga, Hercules);
VidStringType = String[80];
{ Record used to invoke INT 10H when needed }
VidRegs = record
ax, bx, cx, dx, bp, si, di, ds, es, flags: Integer
end;
Raster = Record { Graphics raster descriptor }
Offset, Segment : integer;
Width : integer;
OrigenX, OrigenY: integer;
CornerX, CornerY: integer
end;
FontDescType = Record { Font graphics descriptor }
FontRaster : Raster;
FontWidth : integer;
FontHeight : integer
end;
BlitParm = Record { Paramaters passed to Blit function }
DestOffset, DestSegment : integer;
SrcOffset, SrcSegment : integer;
TextOffset, TextSegment : integer;
RectOrigenX, RectOrigenY: integer;
RectCornerX, RectCornerY: integer;
PointX, PointY : integer;
Opcode, TextOp : integer
end;
{ Data structure describing the video raster }
GrfDataPtr = ^GraphicsData;
GraphicsData = record
{ Data returned by a call to XGRAPH function VidInit }
DestOff, DestSeg : integer;
RasterWidth : integer;
MinimumX, MinimumY : integer;
MaximumX, MaximumY : integer;
RowMask, ShiftIntr : byte;
HomeOffset, BankOffset : integer;
PixelsPByte : byte;
TextureOff, TextureSeg : integer;
FontFormOff, FontFormSeg: integer;
Font2FormOff, Font2FormSeg: integer;
{ Data that must be initialize base on current video mode and adapter }
Adapter : AdapterType;
VideoMode : integer;
GraphicsOn : boolean;
CurrFont : integer;
BitPixelDensity : integer;
MinX, MinY, MaxX, MaxY : integer
end;
procedure GraphInit(var GrfData:GraphicsData; ModeSelect : integer);
{
Called to make a mode change. If ModeSelect equals -1 then the routine
selects the mode with highest resolutions of the adapter. If
ModeSelect is equal to one of the possible modes (see table above) and
the adapter can support it the mode is selected.
After a mode is selected the variables returned from the XGRAPH function
VidInit are copied into GrfData and the rest of GrfData is initialize
base on the mode.
}
var LocalRegs : VidRegs;
GrfPtr : GrfDataPtr;
LocalAdapter : AdapterType;
LocalVideoMode : integer;
corm, mem, switch : integer;
function EGAPresent(var corm, mem, switch:integer):boolean;
begin
{ Use test suggested on IBM PC seminar proceedings }
LocalRegs.ax:=$1200; LocalRegs.bx:=$FF10; LocalRegs.cx:=$000F;
Intr(VideoInt, LocalRegs);
corm := hi(LocalRegs.bx); mem := lo(LocalRegs.bx);
switch := lo(LocalRegs.cx);
if (switch < $0C) and (corm <= $01) and (mem <= $03) then
EGAPresent := true
else
EGAPresent := false;
end;
function MultiModePresent:boolean;
{ Tests for presence of HP's High resolution adapter }
begin
LocalRegs.ax := VidExtendedFunctions shl 8 + $00;
LocalRegs.bx := $FFFF;
Intr(VideoInt, LocalRegs);
if LocalRegs.bx <> $4850 { 'HP' }
then MultiModePresent := false
else begin
LocalRegs.ax := VidExtendedFunctions shl 8 + $01;
Intr(VideoInt, LocalRegs);
if lo(LocalRegs.ax) = $41
then MultimodePresent := true
else MultimodePresent := false;
end;
end;
function CGAPresent:boolean;
var crt : integer;
begin
Port[$3d4] := $0F;
crt := Port[$3d5];
Port[$3d5]:=$55;
delay(100);
if Port[$3d5] = $55 then begin
CGAPresent := true;
Port[$3d5] := crt end
else CGAPresent:=false;
end;
begin
{ Find out type of Video Adapter }
if EGAPresent(corm,mem,switch) then begin
if corm = $01 then { EGA attached to monochrome monitor }
LocalAdapter := EGAMono
else { EGA attached to color monitor }
if (mem > 0) and (switch = $09) then { EGA and Enhanced monitor }
LocalAdapter := EGAEnh
else { EGA and CGA monitor }
LocalAdapter := EGACga
end
else if MultiModePresent then begin
if (Port[$3DA] and $10)=0 then { Test for 400 line monitor }
LocalAdapter := MultiModeHires
else
LocalAdapter := MultiModeCga;
end
else if CGAPresent then begin
LocalAdapter := CGA
end
else begin { Add Hercules presence test here }
LocalAdapter := Mono
end;
{ See if mode selected is appropiate for Adapter monitor combo }
case LocalAdapter of
CGA, MultiModeCga: begin
if not(ModeSelect in [Video320x200BW .. Video640x200]) then
ModeSelect:=Video640x200;
LocalRegs.ax := VidSetMode shl 8 + ModeSelect;
end;
EGACga : begin
if not(ModeSelect in
[Video320x200BW .. Video640x200, VideoEGA320x200 .. VideoEGA640x200])
then ModeSelect:=VideoEGA640x200;
LocalRegs.ax := VidSetMode shl 8 + ModeSelect;
end;
EGAEnh : begin
if not(ModeSelect in
[Video320x200BW..Video640x200, VideoEGA320x200..VideoEGA640x200,
VideoEGA640x350Color]) then ModeSelect:=VideoEGA640x350Color;
LocalRegs.ax := VidSetMode shl 8 + ModeSelect;
end;
EGAMono: begin
if ModeSelect <> VideoEGA640x350Mono then
ModeSelect:=VideoEGA640x350Mono;
LocalRegs.ax := VidSetMode shl 8 + ModeSelect;
end;
MultiModeHires: begin
if not(ModeSelect in [Video320x200BW..Video640x200,
VideoMulti640x400..VideoMulti320x400]) then
ModeSelect:=VideoMulti640x400;
LocalRegs.ax := VidExtendedFunctions shl 8 + $05;
If ModeSelect = VideoMulti640x400 then LocalRegs.bx:=$0D
else if ModeSelect = VideoMulti320x400 then LocalRegs.bx:=$0E
else LocalRegs.bx := ModeSelect;
end;
Hercules: begin
ModeSelect:=VideoHerculesGraphics;
{ Call procedure to put it on Herc graphics mode here }
end;
else { Unknow video adapter and mode }
ModeSelect := -1;
end;
{ Put it in the appropiate video mode }
if (LocalAdapter in
[CGA, EGACga, EGAEnh, EGAMono, MultiModeHires, MultiModeCga])
and (ModeSelect<>-1) then
Intr(VideoInt, LocalRegs);
{ After the mode is selected, Initialize XGRAPH internal data structures }
LocalRegs.ax := VidInit shl 8; Intr(VideoInt, LocalRegs);
GrfPtr := Ptr(LocalRegs.es, LocalRegs.di);
{ and copy it to our local area, and initializing rest of variables }
GrfData := GrfPtr^;
{ Calculate density of bits to pixels and actual screen size in pixels }
with GrfData do begin
if PixelsPByte in [0,1,2,3] then { Calculate pixel/bit density }
case PixelsPByte of { because VidLine operates in pixels }
3 : BitPixelDensity := 1; { and VidBlit operates in bits. }
2 : BitPixelDensity := 2;
1 : BitPixelDensity := 4;
0 : BitPixelDensity := 8
end
else BitPixelDensity := 1;
MinX := MinimumX div BitPixelDensity; MaxX := MaximumX div BitPixelDensity;
MinY := MinimumY; MaxY := MaximumY;
Adapter := LocalAdapter;
VideoMode := ModeSelect;
if ModeSelect <> -1 then GraphicsOn:=true else GraphicsOn:=false;
if MaxY > 199 then CurrFont:=2 else CurrFont:=1;
end;
end;
procedure WriteChar(ch : char; X, Y: integer; GrfData:GraphicsData);
{
Writes a character to raster using the BitBlit procedure and one of
the build-in fonts (FontNum=1 => use 8x8, FontNum=2 => use 8x14).
}
var FontPtr : ^FontDescType;
LocalBlitParms : BlitParm;
LocalRegs : VidRegs;
begin
with LocalBlitParms do begin
DestOffset := ofs(GrfData); DestSegment := seg(GrfData);
if GrfData.CurrFont = 2 then
FontPtr := Ptr(GrfData.Font2FormSeg,GrfData.Font2FormOff)
else
FontPtr := Ptr(GrfData.FontFormSeg,GrfData.FontFormOff);
SrcOffset := ofs(FontPtr^.FontRaster);
SrcSegment := seg(FontPtr^.FontRaster);
RectOrigenX := X; RectOrigenY := Y;
RectCornerX := X + FontPtr^.FontWidth-1;
RectCornerY := Y + FontPtr^.FontHeight-1;
PointX := ord(ch) * FontPtr^.FontWidth; PointY := 0;
Opcode := BlitS; TextOp := TextS;
end;
LocalRegs.ax := VidBlit shl 8;
LocalRegs.ds := seg(LocalBlitParms); LocalRegs.si := ofs(LocalBlitParms);
LocalRegs.bx := $000F; Intr(VideoInt, LocalRegs);
end; { of WriteChar }
procedure WriteStr(Strng:VidStringType; X, Y:integer; GrfData:GraphicsData);
{
Write the given string at (X,Y). Clipping is done by blit if it does
not fit on the screen.
}
var i : integer;
FontPtr : ^FontDescType;
LocalBlitParms : BlitParm;
LocalRegs : VidRegs;
begin
{ Set up all parameters before going into loop }
with LocalBlitParms do begin
DestOffset := ofs(GrfData); DestSegment := seg(GrfData);
if GrfData.CurrFont= 2 then
FontPtr := Ptr(GrfData.Font2FormSeg,GrfData.Font2FormOff)
else
FontPtr := Ptr(GrfData.FontFormSeg,GrfData.FontFormOff);
SrcOffset := ofs(FontPtr^.FontRaster);
SrcSegment := seg(FontPtr^.FontRaster);
RectOrigenX := X; RectOrigenY := Y;
RectCornerX := X + FontPtr^.FontWidth-1;
RectCornerY := Y + FontPtr^.FontHeight-1;
PointY := 0; Opcode := BlitS; TextOp := TextS;
end;
LocalRegs.ax := VidBlit shl 8;
LocalRegs.ds := seg(LocalBlitParms); LocalRegs.si := ofs(LocalBlitParms);
LocalRegs.bx := $000F;
{ Execute a call to blit per character in string and update X position }
for i:=1 to ord(Strng[0]) do with LocalBlitParms do begin
PointX := ord(Strng[i]) * FontPtr^.FontWidth; Intr(VideoInt, LocalRegs);
RectOrigenX := RectOrigenX + FontPtr^.FontWidth;
RectCornerX := RectCornerX + FontPtr^.FontWidth;
end;
end; { of WriteStr }
procedure WriteInt(Value, X, Y : integer;
Base, Width : integer;
LeftJustify : Boolean;
GrfData : GraphicsData );
{
Writes an integer to the screen at location (X,Y), in the given Base,
within a field of Width and left of right justified. If the number is
bigger than the field the Width and LeftJustify parameters are ignored.
Legal bases are 2, 8, 10, 16. Any other base is ignored.
}
var i, temp, Select, Shift, ShiftDec : integer;
Strng : string[16];
begin
Strng := '';
if Base = 10 then Str(Value,Strng)
else if Base in [2,8,16] then begin
case Base of
2 : begin Select:=$8000; Shift:=15; ShiftDec:=1 end;
8 : begin
if Value < 0 then Strng := Strng+'1'
else Strng := Strng+'0';
Select:=$7000; Shift:=12; ShiftDec:=3
end;
16 : begin Select:=$F000; Shift:=12; ShiftDec:=4 end
end;
while Shift >= 0 do begin
Temp := (Value and Select) shr Shift;
Strng[0] := succ(Strng[0]);
if Temp in [0..9] then
Strng[ord(Strng[0])] := chr(ord('0')+temp)
else
Strng[ord(Strng[0])] := chr(ord('A')+temp-10);
Select := Select shr ShiftDec; Shift := Shift - ShiftDec;
end
end;
if (not LeftJustify) and (Length(Strng) < Width) then
for i:=1 to (Width - Length(Strng)) do begin
WriteChar(' ',X,Y,GrfData); X:=X+8;
end;
WriteStr(Strng, X, Y, GrfData);
X := X + (Length(Strng) shl 3);
if LeftJustify and (Length(Strng) < Width) then
for i:=1 to (Width - Length(Strng)) do begin
WriteChar(' ',X,Y,GrfData); X:=X+8;
end;
end;
procedure ReadStr(var Inp:VidStringType; x,y:integer; GrfData:GraphicsData);
{
Reads a string at the given bit position on the screen. It recognizes
Backspace and carriage return as specials characters. It treats every
thing else as part of the string.
}
const
CR = 13; BS = 8;
var
c : char; i : integer;
LocX, LocY : integer;
begin
Inp := ''; LocX := x; LocY:=y;
repeat
WriteChar(chr($DB),LocX,LocY,GrfData);
read(kbd,c);
if (c = chr(BS)) and (ord(Inp[0])>0) then begin
WriteChar(' ',LocX,LocY,GrfData);
if LocX > x then LocX := LocX - 8;
Inp[0]:=pred(Inp[0]);
end
else if (c <> chr(CR)) and (c <> chr(BS)) then begin
WriteChar(c,LocX,LocY,GrfData);
if (LocX+8) < (GrfData.MaximumX) then LocX:=LocX+8;
if (ord(Inp[0]) < 80) then begin
Inp[0] := succ(Inp[0]);
Inp[ord(Inp[0])]:=c;
end;
end;
until (c = chr(CR));
WriteChar(' ',LocX,LocY,GrfData);
end; { of ReadStr }